package com.xx.jenkinsdemo.config;

import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Exchange;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.boot.autoconfigure.amqp.RabbitTemplateConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.converter.MappingJackson2MessageConverter;
import org.springframework.messaging.handler.annotation.support.DefaultMessageHandlerMethodFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * @title: RabbitMqConfig
 * @Author xu-xiang
 * @Date: 2025/7/8 11:09
 * @description:
 */
@Configuration
@EnableRabbit
public class RabbitMqConfig {

    @Bean
    public RabbitTemplate rabbitTemplate(RabbitTemplateConfigurer configurer, ConnectionFactory connectionFactory) {
        // 匿名内部类,直接对消息增强
        // 如果没有设置消息id,则自动设置消息id
        RabbitTemplate template = new RabbitTemplate() {
            @Override
            protected Message convertMessageIfNecessary(Object object) {
                Message message = super.convertMessageIfNecessary(object);

                if (StringUtils.isEmpty(message.getMessageProperties().getMessageId())) {
                    message.getMessageProperties().setMessageId(UUID.randomUUID().toString());
                }
                return message;
            }
        };
        configurer.configure(template, connectionFactory);
        return template;
    }

    @Bean
    public Jackson2JsonMessageConverter jsonMessageConverter() {
        return new Jackson2JsonMessageConverter();
    }

    @Bean
    public DefaultMessageHandlerMethodFactory defaultMessageHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory factory = new DefaultMessageHandlerMethodFactory();
        factory.setMessageConverter(new MappingJackson2MessageConverter());
        return factory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }

    // 定义普通交换机
    @Bean
    public Exchange baseExchange() {
        return new DirectExchange("baseExchange", true, false);
    }

    // 定义普通队列
    @Bean
    public Queue baseQueue() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-message-ttl", 5000); // 消息生存时间为5秒
        args.put("x-dead-letter-exchange", "baseDeadLetterExchange"); // 绑定死信交换机
        args.put("x-dead-letter-routing-key", "baseDeadLetterKey"); // 绑定死信路由键
        return new Queue("baseQueue", true, false, false, args);
    }

    // 绑定普通队列到普通交换机
    @Bean
    public Binding baseBinding() {
        return BindingBuilder.bind(baseQueue())
                .to(baseExchange())
                .with("baseKey")
                .noargs();
    }

    // 定义死信交换机
    @Bean
    public Exchange baseDeadLetterExchange() {
        return new DirectExchange("baseDeadLetterExchange", true, false);
    }

    // 定义死信队列
    @Bean
    public Queue baseDeadLetterQueue() {
        return new Queue("baseDeadLetterQueue", true, false, false);
    }

    // 绑定死信队列到死信交换机
    @Bean
    public Binding baseDeadLetterBinding() {
        return BindingBuilder.bind(baseDeadLetterQueue())
                .to(baseDeadLetterExchange())
                .with("baseDeadLetterKey")
                .noargs();
    }

    // 定义延迟交换机
    @Bean
    public Exchange delayedExchange() {
        Map<String, Object> arguments = new HashMap<>(2);
        arguments.put("x-delayed-type", "direct");

        //交换机的名称、交换机的类型、是否需要持久化、是否需要自动删除、其他参数
        return new CustomExchange("delayedExchange", "x-delayed-message", true, false, arguments);
    }

    // 定义队列
    @Bean
    public Queue delayedQueue() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-message-ttl", 5000); // 消息生存时间为5秒
        args.put("x-dead-letter-exchange", "baseDeadLetterExchange"); // 死信交换机
        args.put("x-dead-letter-routing-key", "baseDeadLetterKey"); // 死信路由键
        // 还是普通队列, 消费失败发往死信队列
        return new Queue("delayedQueue", true, false, false, args);
    }

    // 绑定延迟队列到延迟交换机
    @Bean
    public Binding delayedBinding() {
        return BindingBuilder.bind(delayedQueue())
                .to(delayedExchange())
                .with("delayedKey")
                .noargs();
    }
}
